Skip to content

Enhance save_state method with warnings handling#444

Open
tentpegbob wants to merge 1 commit into
strands-agents:mainfrom
tentpegbob:patch-1
Open

Enhance save_state method with warnings handling#444
tentpegbob wants to merge 1 commit into
strands-agents:mainfrom
tentpegbob:patch-1

Conversation

@tentpegbob
Copy link
Copy Markdown

Description

ReplState.save_state() hangs indefinitely when the REPL namespace contains an enum (or other type with recursive __main__ self-references). The dill.dumps() picklability test enters exponential recursion, emitting thousands of PicklingWarnings before RecursionError eventually propagates to the except BaseException handler.

Impact: Any agent using python_repl that executes code defining an enum class will hang on the next save_state() call, blocking the entire agent process.

When dill.dumps() encounters an enum defined in __main__, it tries to pickle by reference. The qualified name __main__.Constants resolves back to the namespace containing Constants, which itself has members that reference the class — creating infinite recursion. Before RecursionError propagates, dill emits a PicklingWarning at each recursion level. With Python's default recursion limit of 1000, this creates an exponential blowup of warnings and CPU time that effectively hangs the process.

The existing except BaseException: continue on line 223 is correct but never reached in time — dill spends minutes in recursive attempts before the exception fires.

Related Issues

N/A

Documentation PR

N/A

Type of Change

Bug fix

Testing

Two targeted changes in save_state():

  1. Tight recursion limit during dill.dumps() testsys.setrecursionlimit(200) before each picklability test, restored in finally. Self-referencing objects hit RecursionError in milliseconds instead of minutes.

  2. Suppress dill PicklingWarningwarnings.catch_warnings() context manager filters dill warnings during both the per-object test and the final dill.dump(). These warnings are noise (the except handler already skips unpicklable objects).

Reproduction

import enum
from strands_tools import python_repl

class Constants(enum.Enum):
    VALUE_A = "a"
    VALUE_B = "b"

repl = python_repl.ReplState()
repl._namespace["Constants"] = Constants
repl.save_state()  # HANGS here without the fix

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

`ReplState.save_state()` hangs indefinitely when the REPL namespace contains an enum (or other type with recursive `__main__` self-references). The `dill.dumps()` picklability test enters exponential recursion, emitting thousands of `PicklingWarning`s before `RecursionError` eventually propagates to the `except BaseException` handler.

**Impact:** Any agent using `python_repl` that executes code defining an enum class will hang on the next `save_state()` call, blocking the entire agent process.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant